{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Vanilla CNN \n",
    "Implementation of the Vanilla CNN described in the paper\n",
    "Yue Wu and Tal Hassner, \"Facial Landmark Detection with Tweaked Convolutional Neural Networks\", arXiv preprint arXiv:1511.04031, 12 Nov. 2015. See project page for more information about this project. http://www.openu.ac.il/home/hassner/projects/tcnn_landmarks/\n",
    "\n",
    "Written by Ishay Tubi : ishay2b [at] gmail [dot] com       https://www.linkedin.com/in/ishay2b\n",
    "This script will create the data sets needed to train, test and validate Vanilla CNN.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# first lets set up the enviroment paths\n",
    "import os , sys\n",
    "import cv2 # Assume you have open cv python framework installed\n",
    "import numpy as np\n",
    "\n",
    "# Make sure dlib python path exists on PYTHONPATH else \"pip install dlib\" if needed.\n",
    "import dlib\n",
    "detector=dlib.get_frontal_face_detector() # Load dlib's face detector\n",
    "\n",
    "# import helpers and classes used for the script - Assume the same path as existing notebook\n",
    "from DataRow import DataRow, ErrorAcum, Predictor, getGitRepFolder, createDataRowsFromCSV, getValidWithBBox, writeHD5\n",
    "\n",
    "# Either define CAFFE_ROOT in your enviroment variables or set it here\n",
    "CAFFE_ROOT = os.environ.get('CAFFE_ROOT','~/caffe/distribute')  \n",
    "sys.path.insert(0, CAFFE_ROOT + 'python')\n",
    "import caffe\n",
    "\n",
    "#Load project data paths, and pre calculated train data mean and std images.\n",
    "ROOT = getGitRepFolder()  # ROOT is the git root folder .\n",
    "sys.path.append(os.path.join(ROOT, 'python'))  # Assume git root directory\n",
    "DATA_PATH = os.path.join(ROOT, 'data')\n",
    "CSV_TEST  = os.path.join(ROOT, 'data', 'testImageList.txt')\n",
    "CSV_TRAIN = os.path.join(ROOT, 'data', 'trainImageList.txt')\n",
    "\n",
    "AFW_DATA_PATH = os.path.join(ROOT, 'data', 'testimages')\n",
    "AFW_MAT_PATH = os.path.join(ROOT, 'data', 'anno-v7.mat')\n",
    "\n",
    "PATH_TO_WEIGHTS  = os.path.join(ROOT, 'ZOO', 'vanillaCNN.caffemodel')\n",
    "PATH_TO_DEPLOY_TXT = os.path.join(ROOT, 'ZOO', 'vanilla_deploy.prototxt')\n",
    "\n",
    "MEAN_TRAIN_SET = cv2.imread(os.path.join(ROOT, 'trainMean.png')).astype('f4')\n",
    "STD_TRAIN_SET  = cv2.imread(os.path.join(ROOT, 'trainSTD.png')).astype('f4')\n",
    "\n",
    "MEAN_TRAIN_SET = cv2.imread(os.path.join(ROOT, 'trainMean.png')).astype('f4')\n",
    "STD_TRAIN_SET  = cv2.imread(os.path.join(ROOT, 'trainSTD.png')).astype('f4')\n",
    "\n",
    "\n",
    "from pickle import load, dump #We will use pickle to save and load data\n",
    "from zipfile import ZipFile\n",
    "from urllib import urlretrieve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x15167b790>"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x12e852510>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Lets see the train data mean\n",
    "MEAN_TRAIN_SET = cv2.imread(os.path.join(ROOT, 'trainMean.png')).astype('f4')\n",
    "STD_TRAIN_SET  = cv2.imread(os.path.join(ROOT, 'trainSTD.png')).astype('f4')\n",
    "\n",
    "%matplotlib inline\n",
    "from matplotlib.pylab import *\n",
    "imshow(cv2.cvtColor(MEAN_TRAIN_SET, cv2.COLOR_BGR2RGB).astype('uint8'))\n",
    "title (\"Training set mean data\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "###########################    STEPS TO RUN       ####################\n",
    "AFW_STEPS =['downloadAFW', \n",
    "            'createAFW_TestSet',\n",
    "            'testAFW_TestSet'] # Steps needed for AFW\n",
    "\n",
    "AFLW_STEPS=['downloadAFLW', \n",
    "            'testSetHD5', \n",
    "            'testSetPickle', \n",
    "            'testError',\n",
    "            'trainSetHD5', \n",
    "            'createAFLW_TestSet', \n",
    "            'testAFLW_TestSet', \n",
    "            'testErrorMini'] # Steps needed for AFLW\n",
    "\n",
    "STEPS =AFLW_STEPS+AFW_STEPS # Run AFLW and AFW steps\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading http://mmlab.ie.cuhk.edu.hk/archive/CNN/data/train.zip .....\n",
      "Finished downloading AFLW.....\n",
      "Extracting zip data...\n",
      "Done extracting AFLW zip folder\n"
     ]
    }
   ],
   "source": [
    "# Download AFLW train set\n",
    "\n",
    "if 'downloadAFLW' in STEPS:\n",
    "    theurl='http://mmlab.ie.cuhk.edu.hk/archive/CNN/data/train.zip'\n",
    "    filename = ROOT+'/AFLW.zip'\n",
    "    if os.path.isfile(filename):\n",
    "        print \"AFLW.zip training data already downloaded\"\n",
    "    else:\n",
    "        print \"Downloading \"+theurl + \" .....\"\n",
    "        name, hdrs = urlretrieve(theurl, filename)\n",
    "        print \"Finished downloading AFLW.....\"\n",
    "\n",
    "    print 'Extracting zip data...'\n",
    "    folderPATH = ROOT+'/data'\n",
    "    with ZipFile(filename) as theOpenedFile:\n",
    "        theOpenedFile.extractall(folderPATH)\n",
    "        theOpenedFile.close()\n",
    "    print \"Done extracting AFLW zip folder\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading https://www.ics.uci.edu/~xzhu/face/AFW.zip .....\n",
      "Finished downloading AFW.....\n",
      "Extracting AFW zip file......\n"
     ]
    }
   ],
   "source": [
    "if 'downloadAFW' in STEPS:\n",
    "    theurl = 'https://www.ics.uci.edu/~xzhu/face/AFW.zip'\n",
    "    filename = ROOT+'/AFW.zip'\n",
    "    if os.path.isfile(filename):\n",
    "        print \"AFW.zip already downloaded\"\n",
    "    else:\n",
    "        print \"Downloading \"+theurl + \" .....\"\n",
    "        name, hdrs = urlretrieve(theurl, filename)\n",
    "        print \"Finished downloading AFW.....\"\n",
    "        \n",
    "    print \"Extracting AFW zip file......\"\n",
    "    folderPATH = ROOT+'/data'\n",
    "    with ZipFile(filename) as theOpenedFile:\n",
    "        theOpenedFile.extractall(folderPATH)\n",
    "        theOpenedFile.close()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating test set.....\n",
      "Finished reading 3466 rows from test\n",
      "Original test: 3466 Valid Rows: 3431  noFacesAtAll 32  outside: 1  couldNotMatch: 2\n",
      "Finished dumping to testSet.pickle\n",
      "Finished dumping to testSetMini.pickle\n",
      "Processing row 1 \n",
      "Processing row 1001 \n",
      "Processing row 2001 \n",
      "Processing row 3001 \n",
      "Processing row 3431 \n",
      "Finished writing test to caffeData/test.txt\n"
     ]
    }
   ],
   "source": [
    "# Create test set for caffe and python\n",
    "if 'testSetHD5' in STEPS or 'testSetPickle' in STEPS:\n",
    "    print \"Creating test set.....\"\n",
    "    dataRowsTest_CSV  = createDataRowsFromCSV(CSV_TEST , DataRow.DataRowFromNameBoxInterlaved, DATA_PATH)\n",
    "    print \"Finished reading %d rows from test\" % len(dataRowsTest_CSV)\n",
    "    dataRowsTestValid,R = getValidWithBBox(dataRowsTest_CSV)\n",
    "    print \"Original test:\",len(dataRowsTest_CSV), \"Valid Rows:\", len(dataRowsTestValid), \" noFacesAtAll\", R.noFacesAtAll, \" outside:\", R.outsideLandmarks, \" couldNotMatch:\", R.couldNotMatch\n",
    "    if 'testSetPickle' in STEPS:\n",
    "        with open('testSet.pickle','w') as f:\n",
    "            dump(dataRowsTestValid,f)\n",
    "        print \"Finished dumping to testSet.pickle\"\n",
    "        # Also save mini test set for debug\n",
    "        with open('testSetMini.pickle','w') as f:\n",
    "            dump(dataRowsTestValid[0:10],f)\n",
    "        print \"Finished dumping to testSetMini.pickle\"\n",
    "        \n",
    "        \n",
    "    if 'testSetHD5' in STEPS:\n",
    "        writeHD5(dataRowsTestValid, ROOT+'/caffeData/hd5/test.hd5', ROOT+'/caffeData/test.txt', MEAN_TRAIN_SET, STD_TRAIN_SET)\n",
    "        print \"Finished writing test to caffeData/test.txt\"\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running Sanity check\n",
      "Sanity check: Test Error mini: 6.029048 mean error, 10 items, 0 failures  0.000000 precent\n"
     ]
    }
   ],
   "source": [
    "#Sanity check - test and plot mini batch\n",
    "DEBUG = True\n",
    "if 'testErrorMini' in STEPS:\n",
    "    print \"Running Sanity check\"\n",
    "    with open('testSetMini.pickle','r') as f:\n",
    "        dataRowsTrainValid = load(f)\n",
    "        \n",
    "    testErrorMini=ErrorAcum()\n",
    "    predictor = Predictor(protoTXTPath=PATH_TO_DEPLOY_TXT, weightsPath=PATH_TO_WEIGHTS)\n",
    "    for i, dataRow in enumerate(dataRowsTrainValid):\n",
    "        dataRow40 = dataRow.copyCroppedByBBox(dataRow.fbbox).copyMirrored()\n",
    "        image, lm_0_5 = predictor.preprocess(dataRow40.image, dataRow40.landmarks())\n",
    "        prediction = predictor.predict(image)\n",
    "        testErrorMini.add(lm_0_5, prediction)\n",
    "        dataRow40.prediction = (prediction+0.5)*40.  # Scale -0.5..+0.5 to 0..40\n",
    "        \n",
    "        if DEBUG:\n",
    "            dataRow.prediction = dataRow40.inverseScaleAndOffset(dataRow40.prediction) # Scale up to the original image scale\n",
    "            dataRow.show()\n",
    "            if i>40:\n",
    "                print \"Debug breaked after %d rows:\" % i\n",
    "            \n",
    "\n",
    "    print \"Sanity check: Test Error mini:\", testErrorMini\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: 5.946673 mean error, 3431 items, 238 failures  0.069368 precent\n"
     ]
    }
   ],
   "source": [
    "# Run the same caffe test set using python\n",
    "DEBUG = False  # Set this to true if you wish to plot the images\n",
    "if 'testError' in STEPS:\n",
    "    with open('testSet.pickle','r') as f:\n",
    "        dataRowsTrainValid = load(f)\n",
    "        \n",
    "    testError=ErrorAcum()\n",
    "    predictor = Predictor(protoTXTPath=PATH_TO_DEPLOY_TXT, weightsPath=PATH_TO_WEIGHTS)\n",
    "    for i, dataRow in enumerate(dataRowsTrainValid):\n",
    "        dataRow40 = dataRow.copyCroppedByBBox(dataRow.fbbox)\n",
    "        image, lm40 = predictor.preprocess(dataRow40.image, dataRow40.landmarks())\n",
    "        prediction = predictor.predict(image)\n",
    "        testError.add(lm40, prediction)\n",
    "        dataRow40.prediction = (prediction+0.5)*40.\n",
    "        \n",
    "        if DEBUG and i%40 ==0:\n",
    "            dataRow.prediction = dataRow40.inverseScaleAndOffset(dataRow40.prediction)\n",
    "            dataRow.show()\n",
    "            break\n",
    "        \n",
    "            \n",
    "    print \"Test Error:\", testError\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finished reading 10000 rows from training data. Parsing BBox....\n",
      "Original train: 10000 Valid Rows: 9848  No faces at all 142  Illegal landmarks: 6  Coult not math: 4\n",
      "Processing row 1 \n",
      "Processing row 1001 \n",
      "Processing row 2001 \n",
      "Processing row 3001 \n",
      "Processing row 4001 \n",
      "Processing row 5001 \n",
      "Processing row 6001 \n",
      "Processing row 7001 \n",
      "Processing row 8001 \n",
      "Processing row 9001 \n",
      "Processing row 10001 \n",
      "Processing row 11001 \n",
      "Processing row 12001 \n",
      "Processing row 13001 \n",
      "Processing row 14001 \n",
      "Processing row 15001 \n",
      "Processing row 16001 \n",
      "Processing row 17001 \n",
      "Processing row 18001 \n",
      "Processing row 19001 \n",
      "Finished writing train to caffeData/train.txt\n"
     ]
    }
   ],
   "source": [
    "# Create the traning set\n",
    "if 'trainSetHD5' in STEPS:\n",
    "    dataRowsTrain_CSV = createDataRowsFromCSV(CSV_TRAIN, DataRow.DataRowFromNameBoxInterlaved, DATA_PATH)\n",
    "    print \"Finished reading %d rows from training data. Parsing BBox....\" % len(dataRowsTrain_CSV)\n",
    "    dataRowsTrainValid,R = getValidWithBBox(dataRowsTrain_CSV)\n",
    "    print \"Original train:\",len(dataRowsTrain_CSV), \"Valid Rows:\", len(dataRowsTrainValid), \" No faces at all\", R.noFacesAtAll, \" Illegal landmarks:\", R.outsideLandmarks, \" Coult not math:\", R.couldNotMatch\n",
    "    dataRowsTrain_CSV=[]  # remove from memory\n",
    "    \n",
    "    writeHD5(dataRowsTrainValid, ROOT+'/caffeData/hd5/train.hd5', ROOT+'/caffeData/train.txt', MEAN_TRAIN_SET, STD_TRAIN_SET ,mirror=True)\n",
    "    print \"Finished writing train to caffeData/train.txt\"\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parsing AFW anno-v7.mat .....\n",
      "Finished parsing anno-v7.mat with total rows: 170\n",
      "Original AFW: 170 Valid Rows: 141  No faces at all 15  illegal landmarks: 10  Could not match: 4\n",
      "Data saved to afwTestSet.pickle\n"
     ]
    }
   ],
   "source": [
    "# AFW test - Make the pickle data set\n",
    "if 'createAFW_TestSet' in STEPS:\n",
    "    print \"Parsing AFW anno-v7.mat .....\"\n",
    "    from scipy.io import loadmat\n",
    "    annotaions = loadmat(AFW_MAT_PATH)['anno']\n",
    "    dataRowsAFW = []\n",
    "        \n",
    "    for anno in annotaions:\n",
    "        dataRow = DataRow.DataRowFromAFW(anno, AFW_DATA_PATH)\n",
    "        if dataRow is not None:\n",
    "            dataRowsAFW.append(dataRow)\n",
    "    print \"Finished parsing anno-v7.mat with total rows:\", len(dataRowsAFW)\n",
    "    annotaions = None  # remove from memory\n",
    "    \n",
    "    dataRowsAFW_Valid, R=getValidWithBBox(dataRowsAFW)\n",
    "    print \"Original AFW:\", len(dataRowsAFW), \"Valid Rows:\", len(dataRowsAFW_Valid), \" No faces at all\", R.noFacesAtAll, \" illegal landmarks:\", R.outsideLandmarks, \" Could not match:\", R.couldNotMatch\n",
    "    dataRowsAFW = None  # remove from Memory\n",
    "    with open('afwTestSet.pickle','w') as f:\n",
    "        dump(dataRowsAFW_Valid, f)\n",
    "        print \"Data saved to afwTestSet.pickle\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running AFW benchmark.....\n",
      "Test Error AFW: 7.691730 mean error, 141 items, 28 failures  0.198582 precent\n"
     ]
    }
   ],
   "source": [
    "# Run AFW benchmark\n",
    "DEBUG = False\n",
    "if 'testAFW_TestSet' in STEPS:\n",
    "    print \"Running AFW benchmark.....\"\n",
    "    with open('afwTestSet.pickle','r') as f:\n",
    "        dataRowsAFW_Valid = load(f)\n",
    "\n",
    "    testErrorAFW=ErrorAcum()\n",
    "    predictor = Predictor(protoTXTPath=PATH_TO_DEPLOY_TXT, weightsPath=PATH_TO_WEIGHTS)\n",
    "    for i, dataRow in enumerate(dataRowsAFW_Valid):\n",
    "        dataRow40 = dataRow.copyCroppedByBBox(dataRow.fbbox)\n",
    "        image, lm_0_5 = predictor.preprocess(dataRow40.image, dataRow40.landmarks())\n",
    "        prediction = predictor.predict(image)\n",
    "        testErrorAFW.add(lm_0_5, prediction)\n",
    "        dataRow40.prediction = (prediction+0.5)*40.  # Scale -0.5..+0.5 to 0..40\n",
    "        \n",
    "        if DEBUG:\n",
    "            dataRow.prediction = dataRow40.inverseScaleAndOffset(dataRow40.prediction) # Scale up to the original image scale\n",
    "            dataRow.show()\n",
    "            \n",
    "\n",
    "    print \"Test Error AFW:\", testErrorAFW\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading:/Users/ishay/Dev/VanilaCNN/MTFL.zip from url:http://mmlab.ie.cuhk.edu.hk/projects/TCDCN/data/MTFL.zip.....\n",
      "Finished download. Extracting file.....\n",
      "Done extracting MTFL\n",
      "error parsing  ['']\n",
      "Finished reading 2995 rows from test\n",
      "Original test: 2995 Valid Rows: 2535  No faces at all 244  Illegal landmarks: 209  Could not match: 7\n",
      "Finished dumping to testSetMTFL.pickle\n"
     ]
    }
   ],
   "source": [
    "   \n",
    "\n",
    "# Create the MTFL benchmark\n",
    "if 'createAFLW_TestSet' in STEPS:  \n",
    "    MTFL_LINK = 'http://mmlab.ie.cuhk.edu.hk/projects/TCDCN/data/MTFL.zip'\n",
    "    MTFL_ZIP = ROOT+\"/MTFL.zip\"\n",
    "    if os.path.isfile(MTFL_ZIP):\n",
    "        print \"MTFL.zip already downloaded\"\n",
    "    else:\n",
    "        print \"Downloading:\"+MTFL_ZIP+\" from url:\"+MTFL_LINK+\".....\"\n",
    "        urlretrieve(MTFL_LINK, MTFL_ZIP)\n",
    "        print \"Finished download. Extracting file.....\"\n",
    "        with ZipFile(MTFL_ZIP) as f:\n",
    "            f.extractall(ROOT+'/data')\n",
    "            print \"Done extracting MTFL\"\n",
    "            f.close()\n",
    "            \n",
    "    AFLW_PATH = os.path.join(ROOT,'data')\n",
    "    CSV_MTFL = os.path.join(AFLW_PATH,'testing.txt')\n",
    "    dataRowsMTFL_CSV  = createDataRowsFromCSV(CSV_MTFL , DataRow.DataRowFromMTFL, AFLW_PATH)\n",
    "    print \"Finished reading %d rows from test\" % len(dataRowsMTFL_CSV)\n",
    "    dataRowsMTFLValid,R = getValidWithBBox(dataRowsMTFL_CSV)\n",
    "    print \"Original test:\",len(dataRowsMTFL_CSV), \"Valid Rows:\", len(dataRowsMTFLValid), \" No faces at all\", R.noFacesAtAll, \" Illegal landmarks:\", R.outsideLandmarks, \" Could not match:\", R.couldNotMatch\n",
    "    with open('testSetMTFL.pickle','w') as f:\n",
    "        dump(dataRowsMTFLValid,f)\n",
    "    print \"Finished dumping to testSetMTFL.pickle\"        \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running AFLW benchmark.........\n",
      "2535 rows in AFLW benchmark .....\n",
      "Test Error AFLW: 8.313394 mean error, 2535 items, 562 failures  0.221696 precent\n"
     ]
    }
   ],
   "source": [
    "# Run AFLW benchmark\n",
    "DEBUG = False\n",
    "if 'testAFLW_TestSet' in STEPS:\n",
    "    print \"Running AFLW benchmark.........\"\n",
    "    with open('testSetMTFL.pickle','r') as f:\n",
    "        dataRowsAFW_Valid = load(f)\n",
    "    print \"%d rows in AFLW benchmark .....\" % len(dataRowsAFW_Valid)\n",
    "    testErrorAFLW=ErrorAcum()\n",
    "    predictor = Predictor(protoTXTPath=PATH_TO_DEPLOY_TXT, weightsPath=PATH_TO_WEIGHTS)\n",
    "    for i, dataRow in enumerate(dataRowsAFW_Valid):\n",
    "        dataRow40 = dataRow.copyCroppedByBBox(dataRow.fbbox)\n",
    "        image, lm_0_5 = predictor.preprocess(dataRow40.image, dataRow40.landmarks())\n",
    "        prediction = predictor.predict(image)\n",
    "        testErrorAFLW.add(lm_0_5, prediction)\n",
    "        dataRow40.prediction = (prediction+0.5)*40.  # Scale -0.5..+0.5 to 0..40\n",
    "        \n",
    "        if DEBUG and i%40 == 0:\n",
    "            dataRow.prediction = dataRow40.inverseScaleAndOffset(dataRow40.prediction) # Scale up to the original image scale\n",
    "            dataRow.show()\n",
    "\n",
    "\n",
    "    print \"Test Error AFLW:\", testErrorAFLW\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I0226 23:00:03.841297 2061250560 caffe.cpp:177] Use CPU.\n",
      "I0226 23:00:03.842597 2061250560 solver.cpp:48] Initializing solver from parameters: \n",
      "test_iter: 1000\n",
      "test_interval: 5000\n",
      "base_lr: 1e-05\n",
      "display: 2500\n",
      "max_iter: 1400000\n",
      "lr_policy: \"fixed\"\n",
      "momentum: 0.9\n",
      "snapshot: 5000\n",
      "snapshot_prefix: \"../caffeData/snapshots/snap\"\n",
      "solver_mode: CPU\n",
      "net: \"./vanilla_train.prototxt\"\n",
      "momentum2: 0.999\n",
      "type: \"Adam\"\n",
      "I0226 23:00:03.843035 2061250560 solver.cpp:91] Creating training net from net file: ./vanilla_train.prototxt\n",
      "I0226 23:00:03.843643 2061250560 net.cpp:322] The NetState phase (0) differed from the phase (1) specified by a rule in layer \n",
      "I0226 23:00:03.843668 2061250560 net.cpp:49] Initializing net from parameters: \n",
      "name: \"vanila\"\n",
      "state {\n",
      "  phase: TRAIN\n",
      "}\n",
      "layer {\n",
      "  type: \"HDF5Data\"\n",
      "  top: \"X\"\n",
      "  top: \"landmarks\"\n",
      "  include {\n",
      "    phase: TRAIN\n",
      "  }\n",
      "  hdf5_data_param {\n",
      "    source: \"/Users/ishay/Dev/VanilaCNN/caffeData/train.txt\"\n",
      "    batch_size: 30\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv1\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"X\"\n",
      "  top: \"Conv1\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 16\n",
      "    pad: 2\n",
      "    kernel_size: 5\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH1\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv1\"\n",
      "  top: \"ActivationTangH1\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs1\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH1\"\n",
      "  top: \"Abs1\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool1\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs1\"\n",
      "  top: \"Pool1\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 2\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv2\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool1\"\n",
      "  top: \"Conv2\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 48\n",
      "    pad: 1\n",
      "    kernel_size: 3\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH2\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv2\"\n",
      "  top: \"ActivationTangH2\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs2\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH2\"\n",
      "  top: \"Abs2\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool2\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs2\"\n",
      "  top: \"Pool2\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 2\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv3\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool2\"\n",
      "  top: \"Conv3\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 64\n",
      "    pad: 0\n",
      "    kernel_size: 3\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH3\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv3\"\n",
      "  top: \"ActivationTangH3\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs3\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH3\"\n",
      "  top: \"Abs3\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool3\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs3\"\n",
      "  top: \"Pool3\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 3\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv4\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool3\"\n",
      "  top: \"Conv4\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 64\n",
      "    pad: 0\n",
      "    kernel_size: 2\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH4\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv4\"\n",
      "  top: \"ActivationTangH4\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs4\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH4\"\n",
      "  top: \"Abs4\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Dense1\"\n",
      "  type: \"InnerProduct\"\n",
      "  bottom: \"Abs4\"\n",
      "  top: \"Dense1\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  inner_product_param {\n",
      "    num_output: 100\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH5\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Dense1\"\n",
      "  top: \"ActivationTangH5\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs5\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH5\"\n",
      "  top: \"Abs5\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Dense2\"\n",
      "  type: \"InnerProduct\"\n",
      "  bottom: \"Abs5\"\n",
      "  top: \"Dense2\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  inner_product_param {\n",
      "    num_output: 10\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"loss\"\n",
      "  type: \"Python\"\n",
      "  bottom: \"Dense2\"\n",
      "  bottom: \"landmarks\"\n",
      "  top: \"loss\"\n",
      "  loss_weight: 1\n",
      "  python_param {\n",
      "    module: \"python.NormlizedMSE\"\n",
      "    layer: \"NormlizedMSE\"\n",
      "  }\n",
      "}\n",
      "I0226 23:00:03.843927 2061250560 layer_factory.hpp:77] Creating layer \n",
      "I0226 23:00:03.843940 2061250560 net.cpp:106] Creating Layer \n",
      "I0226 23:00:03.843947 2061250560 net.cpp:411]  -> X\n",
      "I0226 23:00:03.843976 2061250560 net.cpp:411]  -> landmarks\n",
      "I0226 23:00:03.843987 2061250560 hdf5_data_layer.cpp:79] Loading list of HDF5 filenames from: /Users/ishay/Dev/VanilaCNN/caffeData/train.txt\n",
      "I0226 23:00:03.844259 2061250560 hdf5_data_layer.cpp:93] Number of HDF5 files: 1\n",
      "I0226 23:00:03.845827 2061250560 hdf5.cpp:32] Datatype class: H5T_FLOAT\n",
      "I0226 23:00:04.505061 2061250560 net.cpp:150] Setting up \n",
      "I0226 23:00:04.505095 2061250560 net.cpp:157] Top shape: 30 3 40 40 (144000)\n",
      "I0226 23:00:04.505107 2061250560 net.cpp:157] Top shape: 30 10 (300)\n",
      "I0226 23:00:04.505115 2061250560 net.cpp:165] Memory required for data: 577200\n",
      "I0226 23:00:04.505128 2061250560 layer_factory.hpp:77] Creating layer Conv1\n",
      "I0226 23:00:04.505146 2061250560 net.cpp:106] Creating Layer Conv1\n",
      "I0226 23:00:04.505158 2061250560 net.cpp:454] Conv1 <- X\n",
      "I0226 23:00:04.505174 2061250560 net.cpp:411] Conv1 -> Conv1\n",
      "I0226 23:00:04.513595 2061250560 net.cpp:150] Setting up Conv1\n",
      "I0226 23:00:04.513613 2061250560 net.cpp:157] Top shape: 30 16 40 40 (768000)\n",
      "I0226 23:00:04.513623 2061250560 net.cpp:165] Memory required for data: 3649200\n",
      "I0226 23:00:04.513638 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH1\n",
      "I0226 23:00:04.513654 2061250560 net.cpp:106] Creating Layer ActivationTangH1\n",
      "I0226 23:00:04.513662 2061250560 net.cpp:454] ActivationTangH1 <- Conv1\n",
      "I0226 23:00:04.513672 2061250560 net.cpp:411] ActivationTangH1 -> ActivationTangH1\n",
      "I0226 23:00:04.513685 2061250560 net.cpp:150] Setting up ActivationTangH1\n",
      "I0226 23:00:04.513691 2061250560 net.cpp:157] Top shape: 30 16 40 40 (768000)\n",
      "I0226 23:00:04.513701 2061250560 net.cpp:165] Memory required for data: 6721200\n",
      "I0226 23:00:04.513708 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs1\n",
      "I0226 23:00:04.513720 2061250560 net.cpp:106] Creating Layer ActivationAbs1\n",
      "I0226 23:00:04.513727 2061250560 net.cpp:454] ActivationAbs1 <- ActivationTangH1\n",
      "I0226 23:00:04.513736 2061250560 net.cpp:411] ActivationAbs1 -> Abs1\n",
      "I0226 23:00:04.513747 2061250560 net.cpp:150] Setting up ActivationAbs1\n",
      "I0226 23:00:04.513754 2061250560 net.cpp:157] Top shape: 30 16 40 40 (768000)\n",
      "I0226 23:00:04.513763 2061250560 net.cpp:165] Memory required for data: 9793200\n",
      "I0226 23:00:04.513769 2061250560 layer_factory.hpp:77] Creating layer Pool1\n",
      "I0226 23:00:04.513779 2061250560 net.cpp:106] Creating Layer Pool1\n",
      "I0226 23:00:04.513787 2061250560 net.cpp:454] Pool1 <- Abs1\n",
      "I0226 23:00:04.513795 2061250560 net.cpp:411] Pool1 -> Pool1\n",
      "I0226 23:00:04.513818 2061250560 net.cpp:150] Setting up Pool1\n",
      "I0226 23:00:04.513823 2061250560 net.cpp:157] Top shape: 30 16 20 20 (192000)\n",
      "I0226 23:00:04.513833 2061250560 net.cpp:165] Memory required for data: 10561200\n",
      "I0226 23:00:04.513839 2061250560 layer_factory.hpp:77] Creating layer Conv2\n",
      "I0226 23:00:04.513852 2061250560 net.cpp:106] Creating Layer Conv2\n",
      "I0226 23:00:04.513859 2061250560 net.cpp:454] Conv2 <- Pool1\n",
      "I0226 23:00:04.513870 2061250560 net.cpp:411] Conv2 -> Conv2\n",
      "I0226 23:00:04.513967 2061250560 net.cpp:150] Setting up Conv2\n",
      "I0226 23:00:04.513974 2061250560 net.cpp:157] Top shape: 30 48 20 20 (576000)\n",
      "I0226 23:00:04.513983 2061250560 net.cpp:165] Memory required for data: 12865200\n",
      "I0226 23:00:04.513994 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH2\n",
      "I0226 23:00:04.514005 2061250560 net.cpp:106] Creating Layer ActivationTangH2\n",
      "I0226 23:00:04.514039 2061250560 net.cpp:454] ActivationTangH2 <- Conv2\n",
      "I0226 23:00:04.514049 2061250560 net.cpp:411] ActivationTangH2 -> ActivationTangH2\n",
      "I0226 23:00:04.514060 2061250560 net.cpp:150] Setting up ActivationTangH2\n",
      "I0226 23:00:04.514066 2061250560 net.cpp:157] Top shape: 30 48 20 20 (576000)\n",
      "I0226 23:00:04.514075 2061250560 net.cpp:165] Memory required for data: 15169200\n",
      "I0226 23:00:04.514081 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs2\n",
      "I0226 23:00:04.514091 2061250560 net.cpp:106] Creating Layer ActivationAbs2\n",
      "I0226 23:00:04.514096 2061250560 net.cpp:454] ActivationAbs2 <- ActivationTangH2\n",
      "I0226 23:00:04.514106 2061250560 net.cpp:411] ActivationAbs2 -> Abs2\n",
      "I0226 23:00:04.514117 2061250560 net.cpp:150] Setting up ActivationAbs2\n",
      "I0226 23:00:04.514123 2061250560 net.cpp:157] Top shape: 30 48 20 20 (576000)\n",
      "I0226 23:00:04.514132 2061250560 net.cpp:165] Memory required for data: 17473200\n",
      "I0226 23:00:04.514138 2061250560 layer_factory.hpp:77] Creating layer Pool2\n",
      "I0226 23:00:04.514150 2061250560 net.cpp:106] Creating Layer Pool2\n",
      "I0226 23:00:04.514160 2061250560 net.cpp:454] Pool2 <- Abs2\n",
      "I0226 23:00:04.514168 2061250560 net.cpp:411] Pool2 -> Pool2\n",
      "I0226 23:00:04.514181 2061250560 net.cpp:150] Setting up Pool2\n",
      "I0226 23:00:04.514188 2061250560 net.cpp:157] Top shape: 30 48 10 10 (144000)\n",
      "I0226 23:00:04.514196 2061250560 net.cpp:165] Memory required for data: 18049200\n",
      "I0226 23:00:04.514204 2061250560 layer_factory.hpp:77] Creating layer Conv3\n",
      "I0226 23:00:04.514216 2061250560 net.cpp:106] Creating Layer Conv3\n",
      "I0226 23:00:04.514222 2061250560 net.cpp:454] Conv3 <- Pool2\n",
      "I0226 23:00:04.514232 2061250560 net.cpp:411] Conv3 -> Conv3\n",
      "I0226 23:00:04.514531 2061250560 net.cpp:150] Setting up Conv3\n",
      "I0226 23:00:04.514539 2061250560 net.cpp:157] Top shape: 30 64 8 8 (122880)\n",
      "I0226 23:00:04.514549 2061250560 net.cpp:165] Memory required for data: 18540720\n",
      "I0226 23:00:04.514562 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH3\n",
      "I0226 23:00:04.514570 2061250560 net.cpp:106] Creating Layer ActivationTangH3\n",
      "I0226 23:00:04.514577 2061250560 net.cpp:454] ActivationTangH3 <- Conv3\n",
      "I0226 23:00:04.514585 2061250560 net.cpp:411] ActivationTangH3 -> ActivationTangH3\n",
      "I0226 23:00:04.514596 2061250560 net.cpp:150] Setting up ActivationTangH3\n",
      "I0226 23:00:04.514602 2061250560 net.cpp:157] Top shape: 30 64 8 8 (122880)\n",
      "I0226 23:00:04.514612 2061250560 net.cpp:165] Memory required for data: 19032240\n",
      "I0226 23:00:04.514619 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs3\n",
      "I0226 23:00:04.514631 2061250560 net.cpp:106] Creating Layer ActivationAbs3\n",
      "I0226 23:00:04.514638 2061250560 net.cpp:454] ActivationAbs3 <- ActivationTangH3\n",
      "I0226 23:00:04.514647 2061250560 net.cpp:411] ActivationAbs3 -> Abs3\n",
      "I0226 23:00:04.514657 2061250560 net.cpp:150] Setting up ActivationAbs3\n",
      "I0226 23:00:04.514664 2061250560 net.cpp:157] Top shape: 30 64 8 8 (122880)\n",
      "I0226 23:00:04.514672 2061250560 net.cpp:165] Memory required for data: 19523760\n",
      "I0226 23:00:04.514679 2061250560 layer_factory.hpp:77] Creating layer Pool3\n",
      "I0226 23:00:04.514688 2061250560 net.cpp:106] Creating Layer Pool3\n",
      "I0226 23:00:04.514694 2061250560 net.cpp:454] Pool3 <- Abs3\n",
      "I0226 23:00:04.514703 2061250560 net.cpp:411] Pool3 -> Pool3\n",
      "I0226 23:00:04.514757 2061250560 net.cpp:150] Setting up Pool3\n",
      "I0226 23:00:04.514775 2061250560 net.cpp:157] Top shape: 30 64 4 4 (30720)\n",
      "I0226 23:00:04.514786 2061250560 net.cpp:165] Memory required for data: 19646640\n",
      "I0226 23:00:04.514796 2061250560 layer_factory.hpp:77] Creating layer Conv4\n",
      "I0226 23:00:04.514811 2061250560 net.cpp:106] Creating Layer Conv4\n",
      "I0226 23:00:04.514818 2061250560 net.cpp:454] Conv4 <- Pool3\n",
      "I0226 23:00:04.514829 2061250560 net.cpp:411] Conv4 -> Conv4\n",
      "I0226 23:00:04.514989 2061250560 net.cpp:150] Setting up Conv4\n",
      "I0226 23:00:04.514997 2061250560 net.cpp:157] Top shape: 30 64 3 3 (17280)\n",
      "I0226 23:00:04.515007 2061250560 net.cpp:165] Memory required for data: 19715760\n",
      "I0226 23:00:04.515018 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH4\n",
      "I0226 23:00:04.515029 2061250560 net.cpp:106] Creating Layer ActivationTangH4\n",
      "I0226 23:00:04.515053 2061250560 net.cpp:454] ActivationTangH4 <- Conv4\n",
      "I0226 23:00:04.515065 2061250560 net.cpp:411] ActivationTangH4 -> ActivationTangH4\n",
      "I0226 23:00:04.515080 2061250560 net.cpp:150] Setting up ActivationTangH4\n",
      "I0226 23:00:04.515087 2061250560 net.cpp:157] Top shape: 30 64 3 3 (17280)\n",
      "I0226 23:00:04.515097 2061250560 net.cpp:165] Memory required for data: 19784880\n",
      "I0226 23:00:04.515105 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs4\n",
      "I0226 23:00:04.515116 2061250560 net.cpp:106] Creating Layer ActivationAbs4\n",
      "I0226 23:00:04.515125 2061250560 net.cpp:454] ActivationAbs4 <- ActivationTangH4\n",
      "I0226 23:00:04.515138 2061250560 net.cpp:411] ActivationAbs4 -> Abs4\n",
      "I0226 23:00:04.515152 2061250560 net.cpp:150] Setting up ActivationAbs4\n",
      "I0226 23:00:04.515159 2061250560 net.cpp:157] Top shape: 30 64 3 3 (17280)\n",
      "I0226 23:00:04.515169 2061250560 net.cpp:165] Memory required for data: 19854000\n",
      "I0226 23:00:04.515177 2061250560 layer_factory.hpp:77] Creating layer Dense1\n",
      "I0226 23:00:04.515192 2061250560 net.cpp:106] Creating Layer Dense1\n",
      "I0226 23:00:04.515199 2061250560 net.cpp:454] Dense1 <- Abs4\n",
      "I0226 23:00:04.515213 2061250560 net.cpp:411] Dense1 -> Dense1\n",
      "I0226 23:00:04.515700 2061250560 net.cpp:150] Setting up Dense1\n",
      "I0226 23:00:04.515709 2061250560 net.cpp:157] Top shape: 30 100 (3000)\n",
      "I0226 23:00:04.515717 2061250560 net.cpp:165] Memory required for data: 19866000\n",
      "I0226 23:00:04.515733 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH5\n",
      "I0226 23:00:04.515743 2061250560 net.cpp:106] Creating Layer ActivationTangH5\n",
      "I0226 23:00:04.515753 2061250560 net.cpp:454] ActivationTangH5 <- Dense1\n",
      "I0226 23:00:04.515766 2061250560 net.cpp:411] ActivationTangH5 -> ActivationTangH5\n",
      "I0226 23:00:04.515779 2061250560 net.cpp:150] Setting up ActivationTangH5\n",
      "I0226 23:00:04.515786 2061250560 net.cpp:157] Top shape: 30 100 (3000)\n",
      "I0226 23:00:04.515795 2061250560 net.cpp:165] Memory required for data: 19878000\n",
      "I0226 23:00:04.515805 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs5\n",
      "I0226 23:00:04.515815 2061250560 net.cpp:106] Creating Layer ActivationAbs5\n",
      "I0226 23:00:04.515822 2061250560 net.cpp:454] ActivationAbs5 <- ActivationTangH5\n",
      "I0226 23:00:04.515832 2061250560 net.cpp:411] ActivationAbs5 -> Abs5\n",
      "I0226 23:00:04.515846 2061250560 net.cpp:150] Setting up ActivationAbs5\n",
      "I0226 23:00:04.515853 2061250560 net.cpp:157] Top shape: 30 100 (3000)\n",
      "I0226 23:00:04.515871 2061250560 net.cpp:165] Memory required for data: 19890000\n",
      "I0226 23:00:04.515877 2061250560 layer_factory.hpp:77] Creating layer Dense2\n",
      "I0226 23:00:04.515889 2061250560 net.cpp:106] Creating Layer Dense2\n",
      "I0226 23:00:04.515897 2061250560 net.cpp:454] Dense2 <- Abs5\n",
      "I0226 23:00:04.515911 2061250560 net.cpp:411] Dense2 -> Dense2\n",
      "I0226 23:00:04.515938 2061250560 net.cpp:150] Setting up Dense2\n",
      "I0226 23:00:04.515943 2061250560 net.cpp:157] Top shape: 30 10 (300)\n",
      "I0226 23:00:04.515947 2061250560 net.cpp:165] Memory required for data: 19891200\n",
      "I0226 23:00:04.515954 2061250560 layer_factory.hpp:77] Creating layer loss\n",
      "I0226 23:00:07.642566 2061250560 net.cpp:106] Creating Layer loss\n",
      "I0226 23:00:07.642601 2061250560 net.cpp:454] loss <- Dense2\n",
      "I0226 23:00:07.642612 2061250560 net.cpp:454] loss <- landmarks\n",
      "I0226 23:00:07.642621 2061250560 net.cpp:411] loss -> loss\n",
      "I0226 23:00:07.642710 2061250560 net.cpp:150] Setting up loss\n",
      "I0226 23:00:07.642720 2061250560 net.cpp:157] Top shape: 1 (1)\n",
      "I0226 23:00:07.642726 2061250560 net.cpp:160]     with loss weight 1\n",
      "I0226 23:00:07.642738 2061250560 net.cpp:165] Memory required for data: 19891204\n",
      "I0226 23:00:07.642743 2061250560 net.cpp:226] loss needs backward computation.\n",
      "I0226 23:00:07.642748 2061250560 net.cpp:226] Dense2 needs backward computation.\n",
      "I0226 23:00:07.642753 2061250560 net.cpp:226] ActivationAbs5 needs backward computation.\n",
      "I0226 23:00:07.642758 2061250560 net.cpp:226] ActivationTangH5 needs backward computation.\n",
      "I0226 23:00:07.642763 2061250560 net.cpp:226] Dense1 needs backward computation.\n",
      "I0226 23:00:07.642768 2061250560 net.cpp:226] ActivationAbs4 needs backward computation.\n",
      "I0226 23:00:07.642792 2061250560 net.cpp:226] ActivationTangH4 needs backward computation.\n",
      "I0226 23:00:07.642798 2061250560 net.cpp:226] Conv4 needs backward computation.\n",
      "I0226 23:00:07.642803 2061250560 net.cpp:226] Pool3 needs backward computation.\n",
      "I0226 23:00:07.642808 2061250560 net.cpp:226] ActivationAbs3 needs backward computation.\n",
      "I0226 23:00:07.642812 2061250560 net.cpp:226] ActivationTangH3 needs backward computation.\n",
      "I0226 23:00:07.642817 2061250560 net.cpp:226] Conv3 needs backward computation.\n",
      "I0226 23:00:07.642822 2061250560 net.cpp:226] Pool2 needs backward computation.\n",
      "I0226 23:00:07.642827 2061250560 net.cpp:226] ActivationAbs2 needs backward computation.\n",
      "I0226 23:00:07.642832 2061250560 net.cpp:226] ActivationTangH2 needs backward computation.\n",
      "I0226 23:00:07.642835 2061250560 net.cpp:226] Conv2 needs backward computation.\n",
      "I0226 23:00:07.642839 2061250560 net.cpp:226] Pool1 needs backward computation.\n",
      "I0226 23:00:07.642843 2061250560 net.cpp:226] ActivationAbs1 needs backward computation.\n",
      "I0226 23:00:07.642848 2061250560 net.cpp:226] ActivationTangH1 needs backward computation.\n",
      "I0226 23:00:07.642853 2061250560 net.cpp:226] Conv1 needs backward computation.\n",
      "I0226 23:00:07.642858 2061250560 net.cpp:228]  does not need backward computation.\n",
      "I0226 23:00:07.642861 2061250560 net.cpp:270] This network produces output loss\n",
      "I0226 23:00:07.642874 2061250560 net.cpp:283] Network initialization done.\n",
      "I0226 23:00:07.643235 2061250560 solver.cpp:181] Creating test net (#0) specified by net file: ./vanilla_train.prototxt\n",
      "I0226 23:00:07.643275 2061250560 net.cpp:322] The NetState phase (1) differed from the phase (0) specified by a rule in layer \n",
      "I0226 23:00:07.643293 2061250560 net.cpp:49] Initializing net from parameters: \n",
      "name: \"vanila\"\n",
      "state {\n",
      "  phase: TEST\n",
      "}\n",
      "layer {\n",
      "  type: \"HDF5Data\"\n",
      "  top: \"X\"\n",
      "  top: \"landmarks\"\n",
      "  include {\n",
      "    phase: TEST\n",
      "  }\n",
      "  hdf5_data_param {\n",
      "    source: \"/Users/ishay/Dev/VanilaCNN/caffeData/test.txt\"\n",
      "    batch_size: 10\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv1\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"X\"\n",
      "  top: \"Conv1\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 16\n",
      "    pad: 2\n",
      "    kernel_size: 5\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH1\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv1\"\n",
      "  top: \"ActivationTangH1\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs1\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH1\"\n",
      "  top: \"Abs1\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool1\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs1\"\n",
      "  top: \"Pool1\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 2\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv2\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool1\"\n",
      "  top: \"Conv2\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 48\n",
      "    pad: 1\n",
      "    kernel_size: 3\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH2\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv2\"\n",
      "  top: \"ActivationTangH2\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs2\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH2\"\n",
      "  top: \"Abs2\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool2\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs2\"\n",
      "  top: \"Pool2\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 2\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv3\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool2\"\n",
      "  top: \"Conv3\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 64\n",
      "    pad: 0\n",
      "    kernel_size: 3\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH3\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv3\"\n",
      "  top: \"ActivationTangH3\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs3\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH3\"\n",
      "  top: \"Abs3\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Pool3\"\n",
      "  type: \"Pooling\"\n",
      "  bottom: \"Abs3\"\n",
      "  top: \"Pool3\"\n",
      "  pooling_param {\n",
      "    pool: MAX\n",
      "    kernel_size: 3\n",
      "    stride: 2\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"Conv4\"\n",
      "  type: \"Convolution\"\n",
      "  bottom: \"Pool3\"\n",
      "  top: \"Conv4\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  convolution_param {\n",
      "    num_output: 64\n",
      "    pad: 0\n",
      "    kernel_size: 2\n",
      "    stride: 1\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "      std: 0.1\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0.2\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH4\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Conv4\"\n",
      "  top: \"ActivationTangH4\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs4\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH4\"\n",
      "  top: \"Abs4\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Dense1\"\n",
      "  type: \"InnerProduct\"\n",
      "  bottom: \"Abs4\"\n",
      "  top: \"Dense1\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  inner_product_param {\n",
      "    num_output: 100\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationTangH5\"\n",
      "  type: \"TanH\"\n",
      "  bottom: \"Dense1\"\n",
      "  top: \"ActivationTangH5\"\n",
      "}\n",
      "layer {\n",
      "  name: \"ActivationAbs5\"\n",
      "  type: \"AbsVal\"\n",
      "  bottom: \"ActivationTangH5\"\n",
      "  top: \"Abs5\"\n",
      "}\n",
      "layer {\n",
      "  name: \"Dense2\"\n",
      "  type: \"InnerProduct\"\n",
      "  bottom: \"Abs5\"\n",
      "  top: \"Dense2\"\n",
      "  param {\n",
      "    lr_mult: 1\n",
      "    decay_mult: 1\n",
      "  }\n",
      "  param {\n",
      "    lr_mult: 2\n",
      "    decay_mult: 0\n",
      "  }\n",
      "  inner_product_param {\n",
      "    num_output: 10\n",
      "    weight_filler {\n",
      "      type: \"xavier\"\n",
      "    }\n",
      "    bias_filler {\n",
      "      type: \"constant\"\n",
      "      value: 0\n",
      "    }\n",
      "  }\n",
      "}\n",
      "layer {\n",
      "  name: \"loss\"\n",
      "  type: \"Python\"\n",
      "  bottom: \"Dense2\"\n",
      "  bottom: \"landmarks\"\n",
      "  top: \"loss\"\n",
      "  loss_weight: 1\n",
      "  python_param {\n",
      "    module: \"python.NormlizedMSE\"\n",
      "    layer: \"NormlizedMSE\"\n",
      "  }\n",
      "}\n",
      "I0226 23:00:07.643532 2061250560 layer_factory.hpp:77] Creating layer \n",
      "I0226 23:00:07.643544 2061250560 net.cpp:106] Creating Layer \n",
      "I0226 23:00:07.643549 2061250560 net.cpp:411]  -> X\n",
      "I0226 23:00:07.643558 2061250560 net.cpp:411]  -> landmarks\n",
      "I0226 23:00:07.643568 2061250560 hdf5_data_layer.cpp:79] Loading list of HDF5 filenames from: /Users/ishay/Dev/VanilaCNN/caffeData/test.txt\n",
      "I0226 23:00:07.643806 2061250560 hdf5_data_layer.cpp:93] Number of HDF5 files: 1\n",
      "I0226 23:00:07.758913 2061250560 net.cpp:150] Setting up \n",
      "I0226 23:00:07.758944 2061250560 net.cpp:157] Top shape: 10 3 40 40 (48000)\n",
      "I0226 23:00:07.758952 2061250560 net.cpp:157] Top shape: 10 10 (100)\n",
      "I0226 23:00:07.758958 2061250560 net.cpp:165] Memory required for data: 192400\n",
      "I0226 23:00:07.758966 2061250560 layer_factory.hpp:77] Creating layer Conv1\n",
      "I0226 23:00:07.758985 2061250560 net.cpp:106] Creating Layer Conv1\n",
      "I0226 23:00:07.758991 2061250560 net.cpp:454] Conv1 <- X\n",
      "I0226 23:00:07.759001 2061250560 net.cpp:411] Conv1 -> Conv1\n",
      "I0226 23:00:07.759052 2061250560 net.cpp:150] Setting up Conv1\n",
      "I0226 23:00:07.759059 2061250560 net.cpp:157] Top shape: 10 16 40 40 (256000)\n",
      "I0226 23:00:07.759068 2061250560 net.cpp:165] Memory required for data: 1216400\n",
      "I0226 23:00:07.759078 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH1\n",
      "I0226 23:00:07.759089 2061250560 net.cpp:106] Creating Layer ActivationTangH1\n",
      "I0226 23:00:07.759096 2061250560 net.cpp:454] ActivationTangH1 <- Conv1\n",
      "I0226 23:00:07.759104 2061250560 net.cpp:411] ActivationTangH1 -> ActivationTangH1\n",
      "I0226 23:00:07.759114 2061250560 net.cpp:150] Setting up ActivationTangH1\n",
      "I0226 23:00:07.759119 2061250560 net.cpp:157] Top shape: 10 16 40 40 (256000)\n",
      "I0226 23:00:07.759126 2061250560 net.cpp:165] Memory required for data: 2240400\n",
      "I0226 23:00:07.759131 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs1\n",
      "I0226 23:00:07.759140 2061250560 net.cpp:106] Creating Layer ActivationAbs1\n",
      "I0226 23:00:07.759145 2061250560 net.cpp:454] ActivationAbs1 <- ActivationTangH1\n",
      "I0226 23:00:07.759151 2061250560 net.cpp:411] ActivationAbs1 -> Abs1\n",
      "I0226 23:00:07.759160 2061250560 net.cpp:150] Setting up ActivationAbs1\n",
      "I0226 23:00:07.759166 2061250560 net.cpp:157] Top shape: 10 16 40 40 (256000)\n",
      "I0226 23:00:07.759171 2061250560 net.cpp:165] Memory required for data: 3264400\n",
      "I0226 23:00:07.759176 2061250560 layer_factory.hpp:77] Creating layer Pool1\n",
      "I0226 23:00:07.759205 2061250560 net.cpp:106] Creating Layer Pool1\n",
      "I0226 23:00:07.759212 2061250560 net.cpp:454] Pool1 <- Abs1\n",
      "I0226 23:00:07.759218 2061250560 net.cpp:411] Pool1 -> Pool1\n",
      "I0226 23:00:07.759229 2061250560 net.cpp:150] Setting up Pool1\n",
      "I0226 23:00:07.759234 2061250560 net.cpp:157] Top shape: 10 16 20 20 (64000)\n",
      "I0226 23:00:07.759240 2061250560 net.cpp:165] Memory required for data: 3520400\n",
      "I0226 23:00:07.759245 2061250560 layer_factory.hpp:77] Creating layer Conv2\n",
      "I0226 23:00:07.759253 2061250560 net.cpp:106] Creating Layer Conv2\n",
      "I0226 23:00:07.759258 2061250560 net.cpp:454] Conv2 <- Pool1\n",
      "I0226 23:00:07.759264 2061250560 net.cpp:411] Conv2 -> Conv2\n",
      "I0226 23:00:07.759356 2061250560 net.cpp:150] Setting up Conv2\n",
      "I0226 23:00:07.759361 2061250560 net.cpp:157] Top shape: 10 48 20 20 (192000)\n",
      "I0226 23:00:07.759366 2061250560 net.cpp:165] Memory required for data: 4288400\n",
      "I0226 23:00:07.759376 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH2\n",
      "I0226 23:00:07.759382 2061250560 net.cpp:106] Creating Layer ActivationTangH2\n",
      "I0226 23:00:07.759387 2061250560 net.cpp:454] ActivationTangH2 <- Conv2\n",
      "I0226 23:00:07.759392 2061250560 net.cpp:411] ActivationTangH2 -> ActivationTangH2\n",
      "I0226 23:00:07.759400 2061250560 net.cpp:150] Setting up ActivationTangH2\n",
      "I0226 23:00:07.759405 2061250560 net.cpp:157] Top shape: 10 48 20 20 (192000)\n",
      "I0226 23:00:07.759412 2061250560 net.cpp:165] Memory required for data: 5056400\n",
      "I0226 23:00:07.759415 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs2\n",
      "I0226 23:00:07.759421 2061250560 net.cpp:106] Creating Layer ActivationAbs2\n",
      "I0226 23:00:07.759426 2061250560 net.cpp:454] ActivationAbs2 <- ActivationTangH2\n",
      "I0226 23:00:07.759434 2061250560 net.cpp:411] ActivationAbs2 -> Abs2\n",
      "I0226 23:00:07.759443 2061250560 net.cpp:150] Setting up ActivationAbs2\n",
      "I0226 23:00:07.759448 2061250560 net.cpp:157] Top shape: 10 48 20 20 (192000)\n",
      "I0226 23:00:07.759454 2061250560 net.cpp:165] Memory required for data: 5824400\n",
      "I0226 23:00:07.759459 2061250560 layer_factory.hpp:77] Creating layer Pool2\n",
      "I0226 23:00:07.759465 2061250560 net.cpp:106] Creating Layer Pool2\n",
      "I0226 23:00:07.759469 2061250560 net.cpp:454] Pool2 <- Abs2\n",
      "I0226 23:00:07.759476 2061250560 net.cpp:411] Pool2 -> Pool2\n",
      "I0226 23:00:07.759485 2061250560 net.cpp:150] Setting up Pool2\n",
      "I0226 23:00:07.759490 2061250560 net.cpp:157] Top shape: 10 48 10 10 (48000)\n",
      "I0226 23:00:07.759495 2061250560 net.cpp:165] Memory required for data: 6016400\n",
      "I0226 23:00:07.759500 2061250560 layer_factory.hpp:77] Creating layer Conv3\n",
      "I0226 23:00:07.759507 2061250560 net.cpp:106] Creating Layer Conv3\n",
      "I0226 23:00:07.759512 2061250560 net.cpp:454] Conv3 <- Pool2\n",
      "I0226 23:00:07.759521 2061250560 net.cpp:411] Conv3 -> Conv3\n",
      "I0226 23:00:07.759799 2061250560 net.cpp:150] Setting up Conv3\n",
      "I0226 23:00:07.759804 2061250560 net.cpp:157] Top shape: 10 64 8 8 (40960)\n",
      "I0226 23:00:07.759810 2061250560 net.cpp:165] Memory required for data: 6180240\n",
      "I0226 23:00:07.759819 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH3\n",
      "I0226 23:00:07.759829 2061250560 net.cpp:106] Creating Layer ActivationTangH3\n",
      "I0226 23:00:07.759834 2061250560 net.cpp:454] ActivationTangH3 <- Conv3\n",
      "I0226 23:00:07.759840 2061250560 net.cpp:411] ActivationTangH3 -> ActivationTangH3\n",
      "I0226 23:00:07.759847 2061250560 net.cpp:150] Setting up ActivationTangH3\n",
      "I0226 23:00:07.759852 2061250560 net.cpp:157] Top shape: 10 64 8 8 (40960)\n",
      "I0226 23:00:07.759858 2061250560 net.cpp:165] Memory required for data: 6344080\n",
      "I0226 23:00:07.759862 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs3\n",
      "I0226 23:00:07.759868 2061250560 net.cpp:106] Creating Layer ActivationAbs3\n",
      "I0226 23:00:07.759873 2061250560 net.cpp:454] ActivationAbs3 <- ActivationTangH3\n",
      "I0226 23:00:07.759879 2061250560 net.cpp:411] ActivationAbs3 -> Abs3\n",
      "I0226 23:00:07.759886 2061250560 net.cpp:150] Setting up ActivationAbs3\n",
      "I0226 23:00:07.759901 2061250560 net.cpp:157] Top shape: 10 64 8 8 (40960)\n",
      "I0226 23:00:07.759907 2061250560 net.cpp:165] Memory required for data: 6507920\n",
      "I0226 23:00:07.759919 2061250560 layer_factory.hpp:77] Creating layer Pool3\n",
      "I0226 23:00:07.759927 2061250560 net.cpp:106] Creating Layer Pool3\n",
      "I0226 23:00:07.759932 2061250560 net.cpp:454] Pool3 <- Abs3\n",
      "I0226 23:00:07.759944 2061250560 net.cpp:411] Pool3 -> Pool3\n",
      "I0226 23:00:07.759968 2061250560 net.cpp:150] Setting up Pool3\n",
      "I0226 23:00:07.759973 2061250560 net.cpp:157] Top shape: 10 64 4 4 (10240)\n",
      "I0226 23:00:07.759977 2061250560 net.cpp:165] Memory required for data: 6548880\n",
      "I0226 23:00:07.759981 2061250560 layer_factory.hpp:77] Creating layer Conv4\n",
      "I0226 23:00:07.759989 2061250560 net.cpp:106] Creating Layer Conv4\n",
      "I0226 23:00:07.759992 2061250560 net.cpp:454] Conv4 <- Pool3\n",
      "I0226 23:00:07.759999 2061250560 net.cpp:411] Conv4 -> Conv4\n",
      "I0226 23:00:07.760151 2061250560 net.cpp:150] Setting up Conv4\n",
      "I0226 23:00:07.760156 2061250560 net.cpp:157] Top shape: 10 64 3 3 (5760)\n",
      "I0226 23:00:07.760161 2061250560 net.cpp:165] Memory required for data: 6571920\n",
      "I0226 23:00:07.760167 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH4\n",
      "I0226 23:00:07.760172 2061250560 net.cpp:106] Creating Layer ActivationTangH4\n",
      "I0226 23:00:07.760176 2061250560 net.cpp:454] ActivationTangH4 <- Conv4\n",
      "I0226 23:00:07.760182 2061250560 net.cpp:411] ActivationTangH4 -> ActivationTangH4\n",
      "I0226 23:00:07.760188 2061250560 net.cpp:150] Setting up ActivationTangH4\n",
      "I0226 23:00:07.760192 2061250560 net.cpp:157] Top shape: 10 64 3 3 (5760)\n",
      "I0226 23:00:07.760197 2061250560 net.cpp:165] Memory required for data: 6594960\n",
      "I0226 23:00:07.760202 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs4\n",
      "I0226 23:00:07.760206 2061250560 net.cpp:106] Creating Layer ActivationAbs4\n",
      "I0226 23:00:07.760210 2061250560 net.cpp:454] ActivationAbs4 <- ActivationTangH4\n",
      "I0226 23:00:07.760215 2061250560 net.cpp:411] ActivationAbs4 -> Abs4\n",
      "I0226 23:00:07.760226 2061250560 net.cpp:150] Setting up ActivationAbs4\n",
      "I0226 23:00:07.760229 2061250560 net.cpp:157] Top shape: 10 64 3 3 (5760)\n",
      "I0226 23:00:07.760234 2061250560 net.cpp:165] Memory required for data: 6618000\n",
      "I0226 23:00:07.760238 2061250560 layer_factory.hpp:77] Creating layer Dense1\n",
      "I0226 23:00:07.760247 2061250560 net.cpp:106] Creating Layer Dense1\n",
      "I0226 23:00:07.760251 2061250560 net.cpp:454] Dense1 <- Abs4\n",
      "I0226 23:00:07.760257 2061250560 net.cpp:411] Dense1 -> Dense1\n",
      "I0226 23:00:07.760691 2061250560 net.cpp:150] Setting up Dense1\n",
      "I0226 23:00:07.760706 2061250560 net.cpp:157] Top shape: 10 100 (1000)\n",
      "I0226 23:00:07.760712 2061250560 net.cpp:165] Memory required for data: 6622000\n",
      "I0226 23:00:07.760723 2061250560 layer_factory.hpp:77] Creating layer ActivationTangH5\n",
      "I0226 23:00:07.760731 2061250560 net.cpp:106] Creating Layer ActivationTangH5\n",
      "I0226 23:00:07.760736 2061250560 net.cpp:454] ActivationTangH5 <- Dense1\n",
      "I0226 23:00:07.760743 2061250560 net.cpp:411] ActivationTangH5 -> ActivationTangH5\n",
      "I0226 23:00:07.760751 2061250560 net.cpp:150] Setting up ActivationTangH5\n",
      "I0226 23:00:07.760756 2061250560 net.cpp:157] Top shape: 10 100 (1000)\n",
      "I0226 23:00:07.760761 2061250560 net.cpp:165] Memory required for data: 6626000\n",
      "I0226 23:00:07.760764 2061250560 layer_factory.hpp:77] Creating layer ActivationAbs5\n",
      "I0226 23:00:07.760771 2061250560 net.cpp:106] Creating Layer ActivationAbs5\n",
      "I0226 23:00:07.760774 2061250560 net.cpp:454] ActivationAbs5 <- ActivationTangH5\n",
      "I0226 23:00:07.760781 2061250560 net.cpp:411] ActivationAbs5 -> Abs5\n",
      "I0226 23:00:07.760787 2061250560 net.cpp:150] Setting up ActivationAbs5\n",
      "I0226 23:00:07.760792 2061250560 net.cpp:157] Top shape: 10 100 (1000)\n",
      "I0226 23:00:07.760797 2061250560 net.cpp:165] Memory required for data: 6630000\n",
      "I0226 23:00:07.760800 2061250560 layer_factory.hpp:77] Creating layer Dense2\n",
      "I0226 23:00:07.760807 2061250560 net.cpp:106] Creating Layer Dense2\n",
      "I0226 23:00:07.760812 2061250560 net.cpp:454] Dense2 <- Abs5\n",
      "I0226 23:00:07.760818 2061250560 net.cpp:411] Dense2 -> Dense2\n",
      "I0226 23:00:07.760838 2061250560 net.cpp:150] Setting up Dense2\n",
      "I0226 23:00:07.760843 2061250560 net.cpp:157] Top shape: 10 10 (100)\n",
      "I0226 23:00:07.760848 2061250560 net.cpp:165] Memory required for data: 6630400\n",
      "I0226 23:00:07.760869 2061250560 layer_factory.hpp:77] Creating layer loss\n",
      "I0226 23:00:07.760915 2061250560 net.cpp:106] Creating Layer loss\n",
      "I0226 23:00:07.760921 2061250560 net.cpp:454] loss <- Dense2\n",
      "I0226 23:00:07.760926 2061250560 net.cpp:454] loss <- landmarks\n",
      "I0226 23:00:07.760932 2061250560 net.cpp:411] loss -> loss\n",
      "I0226 23:00:07.761035 2061250560 net.cpp:150] Setting up loss\n",
      "I0226 23:00:07.761047 2061250560 net.cpp:157] Top shape: 1 (1)\n",
      "I0226 23:00:07.761052 2061250560 net.cpp:160]     with loss weight 1\n",
      "I0226 23:00:07.761060 2061250560 net.cpp:165] Memory required for data: 6630404\n",
      "I0226 23:00:07.761065 2061250560 net.cpp:226] loss needs backward computation.\n",
      "I0226 23:00:07.761070 2061250560 net.cpp:226] Dense2 needs backward computation.\n",
      "I0226 23:00:07.761075 2061250560 net.cpp:226] ActivationAbs5 needs backward computation.\n",
      "I0226 23:00:07.761078 2061250560 net.cpp:226] ActivationTangH5 needs backward computation.\n",
      "I0226 23:00:07.761082 2061250560 net.cpp:226] Dense1 needs backward computation.\n",
      "I0226 23:00:07.761087 2061250560 net.cpp:226] ActivationAbs4 needs backward computation.\n",
      "I0226 23:00:07.761091 2061250560 net.cpp:226] ActivationTangH4 needs backward computation.\n",
      "I0226 23:00:07.761096 2061250560 net.cpp:226] Conv4 needs backward computation.\n",
      "I0226 23:00:07.761099 2061250560 net.cpp:226] Pool3 needs backward computation.\n",
      "I0226 23:00:07.761103 2061250560 net.cpp:226] ActivationAbs3 needs backward computation.\n",
      "I0226 23:00:07.761107 2061250560 net.cpp:226] ActivationTangH3 needs backward computation.\n",
      "I0226 23:00:07.761111 2061250560 net.cpp:226] Conv3 needs backward computation.\n",
      "I0226 23:00:07.761116 2061250560 net.cpp:226] Pool2 needs backward computation.\n",
      "I0226 23:00:07.761121 2061250560 net.cpp:226] ActivationAbs2 needs backward computation.\n",
      "I0226 23:00:07.761124 2061250560 net.cpp:226] ActivationTangH2 needs backward computation.\n",
      "I0226 23:00:07.761128 2061250560 net.cpp:226] Conv2 needs backward computation.\n",
      "I0226 23:00:07.761135 2061250560 net.cpp:226] Pool1 needs backward computation.\n",
      "I0226 23:00:07.761140 2061250560 net.cpp:226] ActivationAbs1 needs backward computation.\n",
      "I0226 23:00:07.761144 2061250560 net.cpp:226] ActivationTangH1 needs backward computation.\n",
      "I0226 23:00:07.761148 2061250560 net.cpp:226] Conv1 needs backward computation.\n",
      "I0226 23:00:07.761152 2061250560 net.cpp:228]  does not need backward computation.\n",
      "I0226 23:00:07.761157 2061250560 net.cpp:270] This network produces output loss\n",
      "I0226 23:00:07.761171 2061250560 net.cpp:283] Network initialization done.\n",
      "I0226 23:00:07.761275 2061250560 solver.cpp:60] Solver scaffolding done.\n",
      "I0226 23:00:07.761329 2061250560 caffe.cpp:212] Starting Optimization\n",
      "I0226 23:00:07.761334 2061250560 solver.cpp:288] Solving vanila\n",
      "I0226 23:00:07.761338 2061250560 solver.cpp:289] Learning Rate Policy: fixed\n",
      "I0226 23:00:07.761584 2061250560 solver.cpp:341] Iteration 0, Testing net (#0)\n"
     ]
    }
   ],
   "source": [
    "# Call caffe to train - Call this from bash \n",
    "# We disable the warning only becuase training aborts and disableing succedes.\n",
    "os.chdir(ROOT+\"/ZOO\")  # Run this from ZOO filder due to local paths in prototxt\n",
    "!caffe.bin train -solver ../ZOO/vanilla_adam_solver.prototxt 2>&1 | tee ../log.txt\n",
    "os.chdir(ROOT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x107cf32d0>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x106268150>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import sys\n",
    "import re\n",
    "%matplotlib inline\n",
    "\n",
    "from matplotlib.pylab import show, title, plot\n",
    "\n",
    "logFilePath = '../log.txt'\n",
    "    \n",
    "floatReg='[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?'\n",
    "\n",
    "regex       =re.compile('.* Iteration (\\d+), Testing net \\(#\\d+\\)')\n",
    "regexLos    =re.compile('.*Test net output #0: loss = (%s) (\\* 1 = %s loss)'%(floatReg,floatReg))\n",
    "regexLos    =re.compile('.*Test net output #0: loss = (%s)'%(floatReg,))\n",
    "\n",
    "found=0\n",
    "\n",
    "xAxis=[]\n",
    "yAxis=[]\n",
    "\n",
    "with open(logFilePath) as f:\n",
    "    global result\n",
    "    for line in f:\n",
    "        xresult = regex.search(line)\n",
    "        if (xresult):\n",
    "            xAxis.append(xresult.groups(1)[0])\n",
    "            \n",
    "        yresult = regexLos.search(line)\n",
    "        if (yresult):\n",
    "            yAxis.append(yresult.groups(1)[0])\n",
    "\n",
    "mnSize = min(len(xAxis),len(yAxis))\n",
    "skip = 0\n",
    "\n",
    "xAxis = xAxis[skip:mnSize]\n",
    "yAxis = yAxis[skip:mnSize]\n",
    "\n",
    "plot(xAxis, yAxis)\n",
    "title('test loss over iterations')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Raw Cell Format",
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
